﻿using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace wojilu
{
    public class PHPSerializer
    {
        private NumberFormatInfo nfi = new NumberFormatInfo();
        private int pos;
        private Dictionary<ArrayList, bool> seenArrayLists;
        private Dictionary<Hashtable, bool> seenHashtables;
        public Encoding StringEncoding = new UTF8Encoding();
        public bool XMLSafe = true;
        public PHPSerializer()
        {
            this.nfi.NumberGroupSeparator = "";
            this.nfi.NumberDecimalSeparator = ".";
        }
        private object deserialize(string str)
        {
            object result;
            if (str == null || str.Length <= this.pos)
            {
                result = new object();
            }
            else
            {
                char c = str[this.pos];
                if (c != 'N')
                {
                    int num;
                    int num2;
                    string text;
                    int num3;
                    switch (c)
                    {
                        case 'a':
                            {
                                num = str.IndexOf(":", this.pos) + 1;
                                num2 = str.IndexOf(":", num);
                                text = str.Substring(num, num2 - num);
                                num3 = int.Parse(text);
                                Hashtable hashtable = new Hashtable(num3);
                                ArrayList arrayList = new ArrayList(num3);
                                this.pos += 4 + text.Length;
                                for (int i = 0; i < num3; i++)
                                {
                                    object obj = this.deserialize(str);
                                    object value = this.deserialize(str);
                                    if (arrayList != null)
                                    {
                                        if (obj is int && (int)obj == arrayList.Count)
                                        {
                                            arrayList.Add(value);
                                        }
                                        else
                                        {
                                            arrayList = null;
                                        }
                                    }
                                    hashtable[obj] = value;
                                }
                                this.pos++;
                                if (this.pos < str.Length && str[this.pos] == ';')
                                {
                                    this.pos++;
                                }
                                if (arrayList != null)
                                {
                                    result = arrayList;
                                    return result;
                                }
                                result = hashtable;
                                return result;
                            }
                        case 'b':
                            {
                                char c2 = str[this.pos + 2];
                                this.pos += 4;
                                result = (c2 == '1');
                                return result;
                            }
                        case 'c':
                            goto IL_38F;
                        case 'd':
                            {
                                num = str.IndexOf(":", this.pos) + 1;
                                num2 = str.IndexOf(";", num);
                                string text2 = str.Substring(num, num2 - num);
                                this.pos += 3 + text2.Length;
                                result = double.Parse(text2, this.nfi);
                                return result;
                            }
                        case 'e':
                        case 'f':
                        case 'g':
                        case 'h':
                            goto IL_38F;
                        case 'i':
                            {
                                num = str.IndexOf(":", this.pos) + 1;
                                num2 = str.IndexOf(";", num);
                                string text3 = str.Substring(num, num2 - num);
                                this.pos += 3 + text3.Length;
                                try
                                {
                                    result = int.Parse(text3, this.nfi);
                                    return result;
                                }
                                catch
                                {
                                    result = long.Parse(text3, this.nfi);
                                    return result;
                                }

                            }
                        default:
                            if (c != 's')
                            {
                                goto IL_38F;
                            }
                            break;
                    }
                    num = str.IndexOf(":", this.pos) + 1;
                    num2 = str.IndexOf(":", num);
                    text = str.Substring(num, num2 - num);
                    int num4 = int.Parse(text);
                    num3 = num4;
                    if (num2 + 2 + num3 >= str.Length)
                    {
                        num3 = str.Length - 2 - num2;
                    }
                    string text4 = str.Substring(num2 + 2, num3);
                    while (this.StringEncoding.GetByteCount(text4) > num4)
                    {
                        num3--;
                        text4 = str.Substring(num2 + 2, num3);
                    }
                    this.pos += 6 + text.Length + num3;
                    if (this.XMLSafe)
                    {
                        text4 = text4.Replace("\n", "\r\n");
                    }
                    result = text4;
                    return result;
                IL_38F:
                    result = "";
                }
                else
                {
                    this.pos += 2;
                    result = null;
                }
            }
            return result;
        }
        public object Deserialize(string str)
        {
            this.pos = 0;
            return this.deserialize(str);
        }
        private StringBuilder serialize(object obj, StringBuilder sb)
        {
            StringBuilder result;
            if (obj == null)
            {
                result = sb.Append("N;");
            }
            else
            {
                if (obj is string)
                {
                    string text = (string)obj;
                    if (this.XMLSafe)
                    {
                        text = text.Replace("\r\n", "\n").Replace("\r", "\n");
                    }
                    result = sb.Append(string.Concat(new object[]
					{
						"s:",
						this.StringEncoding.GetByteCount(text),
						":\"",
						text,
						"\";"
					}));
                }
                else
                {
                    if (obj is bool)
                    {
                        result = sb.Append("b:" + (((bool)obj) ? "1" : "0") + ";");
                    }
                    else
                    {
                        if (obj is int)
                        {
                            result = sb.Append("i:" + ((int)obj).ToString(this.nfi) + ";");
                        }
                        else
                        {
                            if (obj is long)
                            {
                                result = sb.Append("i:" + ((long)obj).ToString(this.nfi) + ";");
                            }
                            else
                            {
                                if (obj is double)
                                {
                                    result = sb.Append("d:" + ((double)obj).ToString(this.nfi) + ";");
                                }
                                else
                                {
                                    if (obj is ArrayList)
                                    {
                                        if (this.seenArrayLists.ContainsKey((ArrayList)obj))
                                        {
                                            result = sb.Append("N;");
                                        }
                                        else
                                        {
                                            this.seenArrayLists.Add((ArrayList)obj, true);
                                            ArrayList arrayList = (ArrayList)obj;
                                            sb.Append("a:" + arrayList.Count + ":{");
                                            for (int i = 0; i < arrayList.Count; i++)
                                            {
                                                this.serialize(i, sb);
                                                this.serialize(arrayList[i], sb);
                                            }
                                            sb.Append("}");
                                            result = sb;
                                        }
                                    }
                                    else
                                    {
                                        if (obj is Hashtable)
                                        {
                                            if (this.seenHashtables.ContainsKey((Hashtable)obj))
                                            {
                                                result = sb.Append("N;");
                                            }
                                            else
                                            {
                                                this.seenHashtables.Add((Hashtable)obj, true);
                                                Hashtable hashtable = (Hashtable)obj;
                                                sb.Append("a:" + hashtable.Count + ":{");
                                                foreach (DictionaryEntry dictionaryEntry in hashtable)
                                                {
                                                    this.serialize(dictionaryEntry.Key, sb);
                                                    this.serialize(dictionaryEntry.Value, sb);
                                                }
                                                sb.Append("}");
                                                result = sb;
                                            }
                                        }
                                        else
                                        {
                                            result = sb;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return result;
        }
        public string Serialize(object obj)
        {
            this.seenArrayLists = new Dictionary<ArrayList, bool>();
            this.seenHashtables = new Dictionary<Hashtable, bool>();
            return this.serialize(obj, new StringBuilder()).ToString();
        }
    }
}
